package com.mrx.commons.trace;

import feign.Client;
import feign.RequestInterceptor;
import okhttp3.Dns;
import okhttp3.OkHttpClient;
import org.jetbrains.annotations.NotNull;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.context.annotation.Bean;

import java.net.InetAddress;
import java.net.UnknownHostException;
import java.util.*;
import java.util.concurrent.TimeUnit;

/**
 * @author Mr.X
 * @since 2023-11-28 11:42
 **/
public class FeignTracer {

    private static final Logger logger = LoggerFactory.getLogger(FeignTracer.class);

    @Bean
    public RequestInterceptor tracerInterceptor() {
        return template -> {
            template.header(TraceUtils.TRACE_HEADER, Collections.singleton(TraceUtils.getTraceId()));
            logger.debug("{}: {}, headers: {}", template.method(), template.url(), template.headers());
        };
    }

    @Bean
    public OkHttpClient okHttpClient(Dns dns) {
        return new OkHttpClient.Builder()
                .callTimeout(1, TimeUnit.MINUTES)
                .connectTimeout(1, TimeUnit.MINUTES)
                .readTimeout(1, TimeUnit.MINUTES)
                .writeTimeout(1, TimeUnit.MINUTES)
                .dns(dns)
                .build();
    }

    @Bean
    @ConditionalOnMissingBean(Client.class)
    public Client feignClient(OkHttpClient client) {
        return new feign.okhttp.OkHttpClient(client);
    }

    @Bean
    public Dns dns() {
        Map<String, Set<String>> hosts = Map.of("httpbin.org", Set.of("104.16.222.8"));
        return new Dns() {
            @NotNull
            @Override
            public List<InetAddress> lookup(@NotNull String host) throws UnknownHostException {
                Set<String> ips = hosts.get(host);
                if (ips == null) {
                    ips = new HashSet<>();
                    ips.add(host);
                }
                logger.debug("Lookup dns: {} -> {}", host, ips);
                List<InetAddress> addresses = new ArrayList<>();
                for (String ip : ips) {
                    addresses.add(InetAddress.getByName(ip));
                }
                return addresses;
            }
        };
    }

}
